home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolf3dmacsource.sit / Wolf3DMacSource / WolfMain.c < prev    next >
C/C++ Source or Header  |  1994-09-30  |  13KB  |  460 lines

  1. #include "wolfdef.h"
  2. #include <string.h>
  3.  
  4. /**********************************
  5.  
  6.     Return the absolute value
  7.     
  8. **********************************/
  9.  
  10. Word w_abs(int val)
  11. {
  12.     return val>=0 ? val : -val;
  13. }
  14.  
  15. /**********************************
  16.  
  17.     Return a seeded random number
  18.     
  19. **********************************/
  20.  
  21. Byte rndtable[256] = {
  22.       0,  8, 109, 220, 222, 241, 149, 107,  75, 248, 254, 140,  16,  66,
  23.      74, 21, 211,  47,  80, 242, 154,  27, 205, 128, 161,  89,  77,  36,
  24.      95,110,  85,  48, 212, 140, 211, 249,  22,  79, 200,  50,  28, 188,
  25.      52,140, 202, 120,  68, 145,  62,  70, 184, 190,  91, 197, 152, 224,
  26.     149,104,  25, 178, 252, 182, 202, 182, 141, 197,   4,  81, 181, 242,
  27.     145, 42,  39, 227, 156, 198, 225, 193, 219,  93, 122, 175, 249,   0,
  28.     175,143,  70, 239,  46, 246, 163,  53, 163, 109, 168, 135,   2, 235,
  29.      25, 92,  20, 145, 138,  77,  69, 166,  78, 176, 173, 212, 166, 113,
  30.      94,161,  41,  50, 239,  49, 111, 164,  70,  60,   2,  37, 171,  75,
  31.     136,156,  11,  56,  42, 146, 138, 229,  73, 146,  77,  61,  98, 196,
  32.     135,106,  63, 197, 195,  86,  96, 203, 113, 101, 170, 247, 181, 113,
  33.      80,250, 108,   7, 255, 237, 129, 226,  79, 107, 112, 166, 103, 241,
  34.      24,223, 239, 120, 198,  58,  60,  82, 128,   3, 184,  66, 143, 224,
  35.     145,224,  81, 206, 163,  45,  63,  90, 168, 114,  59,  33, 159,  95,
  36.      28,139, 123,  98, 125, 196,  15,  70, 194, 253,  54,  14, 109, 226,
  37.      71, 17, 161,  93, 186,  87, 244, 138,  20,  52, 123, 251,  26,  36,
  38.      17, 46,  52, 231, 232,  76,  31, 221,  84,  37, 216, 165, 212, 106,
  39.     197,242,  98,  43,  39, 175, 254, 145, 190,  84, 118, 222, 187, 136,
  40.     120,163, 236, 249
  41. };
  42.  
  43. Word rndindex = 0;
  44.  
  45. Word w_rnd(void)
  46. {
  47.     rndindex = (rndindex+1)&0xff;    /* Next index */
  48.     return rndtable[rndindex];        /* Return the number */
  49. }
  50.  
  51.  
  52. /**********************************
  53.  
  54.     Return an angle value based on a slope.
  55.     Assume that x is >= to y.
  56.         
  57. **********************************/
  58.  
  59. Word AngleFromSlope2(Word y,Word x)
  60. {
  61.     return tantoangle[((LongWord)y<<SLOPEBITS)/x];
  62. }
  63.  
  64. /**********************************
  65.  
  66.     Convert an arbitrary point from the viewxy into an angle.
  67.     
  68.     To get a global angle from cartesian coordinates, the coordinates are flipped until 
  69.     they are in the first octant of the coordinate system, then the y (<=x) is scaled and 
  70.     divided by x to get a tangent (slope) value which is looked up in the tantoangle[] table.
  71.     The +1 size is to handle the case when x==y without additional checking.
  72.     
  73. **********************************/
  74.  
  75. #define    ANG90    0x4000
  76. #define    ANG180    0x8000
  77. #define    ANG270    0xc000
  78. angle_t PointToAngle(fixed_t x, fixed_t y)
  79. {    
  80.     x -= viewx;        /* Adjust the x and y based on the camera */
  81.     y = viewy - y;
  82.     
  83.     if (x>=0) {    /* x is positive? */
  84.         if (y>=0) {    /* y is positive? */
  85.             if (x>y) {
  86.                 return AngleFromSlope2(y,x);    /* octant 0*/
  87.             } else {
  88.                 return ANG90-1-AngleFromSlope2(x,y);    /* octant 1 */
  89.             }
  90.         } else {    /* y<0 */
  91.             y = -y;    /* Negate y (Make positive) */
  92.             if (x>y) {
  93.                 return -AngleFromSlope2(y,x);    /* octant 8 */
  94.             } else {
  95.                 return ANG270+AngleFromSlope2 (x,y);    /* octant 7 */
  96.             }
  97.         }
  98.     } else {    /* x<0*/
  99.         x = -x;    /* Force x positive */
  100.         if (y>= 0) {    /* Is y positive? */
  101.             if (x>y) {
  102.                 return ANG180-1-AngleFromSlope2(y,x);    /* octant 3 */
  103.             } else {
  104.                 return ANG90+AngleFromSlope2(x,y);        /* octant 2 */
  105.             }
  106.         } else {    /* y<0*/
  107.             y = -y;    /* Force y positive also */
  108.             if (x>y) {
  109.                 return ANG180+AngleFromSlope2 (y,x);    /* octant 4 */
  110.             }
  111.         }
  112.     }
  113.     return ANG270-1-AngleFromSlope2(x,y);    /* octant 5 */
  114. }
  115.  
  116. /**********************************
  117.  
  118.     Died() has already spun the view toward the killer
  119.     GameOver() scales the "game over" sprite in and pulses it until an event
  120.  
  121. **********************************/
  122.  
  123. void GameOver(void)
  124. {    
  125.     topspritenum = S_GAMEOVER;        /* Game over words */
  126.     topspritescale = 8;    /* Start the scale factor */
  127.     do {
  128.         RenderView();        /* Draw the 3-d view */
  129.         topspritescale+=8;
  130.     } while (topspritescale<120);
  131.     
  132.     for (;;) {        /* Stay here forever */
  133.         do {
  134.             if (WaitTicksEvent(1)) {    /* Canceled? */
  135.                 return;
  136.             }
  137.             RenderView();                /* Show the 3-D view */
  138.             topspritescale-=2;    /* Make smaller */
  139.         } while(topspritescale>100);    /* Not too small... */
  140.         do {
  141.             if (WaitTicksEvent(1)) {    /* Canceled? */
  142.                 return;
  143.             }
  144.             RenderView();                /* Show the 3-D view */
  145.             topspritescale+=2;    /* Make bigger */
  146.         } while (topspritescale<120);    /* Not too big... */
  147.     }
  148. }
  149.  
  150. /**********************************
  151.  
  152.     Show the word "Victory" scaling in...
  153.     
  154. **********************************/
  155.  
  156. void VictoryScale(void)
  157. {
  158.     topspritenum = S_VICTORY;
  159.     topspritescale = 16;
  160.     
  161.     do {
  162.         RenderView();
  163.         topspritescale += 16;
  164.     } while (topspritescale<240);
  165.     
  166.     for (;;) {
  167.         do {
  168.             if (WaitTicksEvent(1)) {
  169.                 return;
  170.             }
  171.             RenderView();
  172.             topspritescale-=4;
  173.         } while (topspritescale>200);
  174.         do {
  175.             if (WaitTicksEvent(1)) {
  176.                 return;
  177.             }
  178.             RenderView();
  179.             topspritescale+=4;
  180.         } while (topspritescale<240);    
  181.     }
  182. }
  183.  
  184. /**********************************
  185.  
  186.     You died...
  187.     
  188. **********************************/
  189.  
  190. void Died (void)
  191. {
  192.     Word Timer;    /* Time mark */
  193.     Word Adds;        /* Number of tics elapsed */
  194.     Word Total;    
  195.     angle_t    SrcAngle;    /* Angle of view */
  196.     angle_t DestAngle;    /* Angle of death */
  197.     fixed_t Motion;        /* Motion constant */
  198.     
  199.     gamestate.attackframe = 0;        /* Remove the gun shape */
  200.     NoWeaponDraw = TRUE;            /* The weapon is not drawn */
  201.     PlaySound(SND_PDIE);                /* ARRRGGGHHHH!! */
  202.     IO_DrawFace(9);                    /* Show the dead face */
  203.         
  204. /* find angle to face attacker */
  205.  
  206.     SrcAngle = gamestate.viewangle<<SHORTTOANGLESHIFT;        /* Get the fine current angle */
  207.     DestAngle = PointToAngle(killx,killy)&(-1<<SHORTTOANGLESHIFT);    /* What's the direction of the kill angle */    
  208.     
  209. /* rotate to attacker */
  210.  
  211.     if (SrcAngle!=DestAngle) {                /* Do I need to rotate? */
  212.         Motion = (fixed_t)(DestAngle-SrcAngle)/ (fixed_t)30;        /* Differance in fine angles */
  213.         LastTicCount = ReadTick();
  214.         Total = 30;            /* Number of tics to elapse */
  215.         for (;;) {    /* There yet? */
  216.             Timer = ReadTick();        /* How much time has elapsed */
  217.             Adds = Timer-LastTicCount;    /* Save the time */
  218.             LastTicCount = Timer;    /* Mark the new time */
  219.             if (Adds>=Total) {        /* Too much time? */
  220.                 break;                /* Get out now! */
  221.             }
  222.             Total-=Adds;            /* Remove elapsed time */
  223.             SrcAngle += Motion*Adds;    /* Spin */
  224.             gamestate.viewangle = SrcAngle>>SHORTTOANGLESHIFT;    /* Set the new view angle */
  225.             RenderView();        /* Show the view */
  226.         }                
  227.         gamestate.viewangle = DestAngle>>SHORTTOANGLESHIFT;        /* Finish the motion */
  228.         RenderView();            /* Draw the screen */
  229.     }
  230. /* done */
  231.  
  232.     if (!gamestate.lives) {
  233.         GameOver();            /* Show Game over... */
  234.     } else {
  235.         WaitEvent();            /* Wait for an event */
  236.         gamestate.health = 100;    /* Restore health */
  237.         if (difficulty) {        /* Remove weapons if difficult */
  238.             gamestate.weapon = gamestate.pendingweapon = WP_PISTOL;
  239.             gamestate.machinegun = FALSE;
  240.             gamestate.chaingun = FALSE;
  241.             gamestate.missile = FALSE;
  242.             gamestate.flamethrower = FALSE;
  243.             gamestate.ammo = STARTAMMO;
  244.             gamestate.missiles = 0;
  245.             gamestate.gas = 0;
  246.             gamestate.maxammo = 99;
  247.             gamestate.keys = 0;
  248.         } else {
  249.             if (gamestate.ammo < STARTAMMO*2) {    /* If easy, then reload... */
  250.                 gamestate.ammo = STARTAMMO*2;
  251.             }
  252.         }
  253.         gamestate.attackframe = 0;        /* Reset the attack frame */
  254.         gamestate.attackcount = 0;
  255.     }
  256.     FadeToBlack();            /* Fade the screen to black */
  257. }
  258.  
  259. /**********************************
  260.  
  261.     Calls draw face if time to change
  262.     
  263. **********************************/
  264.  
  265. void UpdateFace(void)
  266. {
  267.     Word Base;
  268.     
  269.     if (facecount>TicCount) {    /* Time to change the face? */
  270.         facecount-=TicCount;    /* Wait a bit */
  271.     } else {
  272.         Base = (gamestate.health <= 25) ? 5 : 0;
  273.         if (faceframe==Base) {    /* Normal frame? */
  274.             ++Base;        /* Use alternate */
  275.         }
  276.         faceframe=Base;    /* Set the new face */
  277.         facecount = (w_rnd ()&31)+4;    /* Random time */
  278.         IO_DrawFace(faceframe);        /* Draw the face */
  279.     }
  280. }
  281.  
  282. /**********************************
  283.  
  284.     Prepare for a game loop
  285.     
  286. **********************************/
  287.  
  288. void PrepPlayLoop (void)
  289. {
  290.     StartSong(SongListPtr[gamestate.mapon+2]);    /* start music */
  291.     if (!SetupGameLevel()) {    /* Load the game map */
  292.         ReleaseMap();            /* Release map memory */
  293.         ReleaseScalers();        /* Release the compiled scalers */
  294.         PlaySong(0);
  295.         while (!SetupGameLevel()) {    /* Try loading it again */
  296. Again:
  297.             ReleaseMap();        /* Oh oh... */
  298.             if (!GameViewSize) {    /* Smallest screen? */
  299.                 BailOut();        /* Leave... */
  300.             }
  301.             --GameViewSize;        /* Smaller screen size */
  302.             GameViewSize = NewGameWindow(GameViewSize);
  303.         }
  304.     }
  305.     if (!StartupRendering(GameViewSize)) {
  306.         ReleaseScalers();
  307.         goto Again;
  308.     }
  309.     topspritescale = 0;    /* No overlay sprite */
  310.     faceframe = 1;        /* First face */
  311.     facecount = 1;        /* change face next tic */
  312.     firstframe = 1;        /* Force a fade in */
  313.     NoWeaponDraw = 0;    /* Allow drawing of weapon */
  314.     memset(buttonstate,0,sizeof(buttonstate));    /* Kill the mouse system */
  315.     if (playstate!=EX_LOADGAME) {
  316.         PushWallRec.pwallcount = 0;        /* No pushwalls */
  317.         gamestate.playtime = 0;        /* Game has started */
  318.     } else {
  319.         FinishLoadGame();            /* Finish the load game code */
  320.     }
  321.     RedrawStatusBar();    /* Redraw the main bar */
  322.     mousey = 0;            /* Reset the mouse y */
  323.     playstate = EX_STILLPLAYING;    /* Game is in progress */
  324. }
  325.  
  326. /**********************************
  327.  
  328.     Play the game
  329.     
  330. **********************************/
  331.  
  332. void PlayLoop(void)
  333. {
  334.     LongWord Timer;
  335.     LastTicCount = ReadTick();
  336.     do {
  337.         Timer = ReadTick();        /* How much time has elapsed */
  338.         TicCount = (Timer-LastTicCount);
  339.         gamestate.playtime += TicCount;    /* Add the physical time to the elapsed time */
  340.         
  341.         LastTicCount=Timer;
  342.         if (!SlowDown) {
  343.             TicCount = 4;        /* Adjust from 4 */
  344.         }
  345.         if (TicCount>=5) {
  346.             TicCount = 4;
  347.         }
  348.         IO_CheckInput();    /* Read the controls from the system */
  349.         madenoise = FALSE;    /* No noise made (Yet) */
  350.         MoveDoors();        /* Open and close all doors */
  351.         MovePWalls();        /* Move all push walls */
  352.         MovePlayer();        /* Move the player */
  353.         MoveActors();        /* Move all the bad guys */
  354.         MoveMissiles();        /* Move all projectiles */    
  355.         UpdateFace();        /* Draw BJ's face and animate it */
  356.         viewx = actors[0].x;    /* Where is the camera? */
  357.         viewy = actors[0].y;        
  358.         RenderView();        /* Draw the 3D view */
  359.     } while (playstate==EX_STILLPLAYING);
  360.     StopSong();
  361. }
  362.  
  363. /**********************************
  364.  
  365.     Set up new game to start from the beginning
  366.  
  367. **********************************/
  368.  
  369. void NewGame(void)
  370. {
  371.     nextmap = 0;            /* No next map inited */
  372.     memset(&gamestate,0,sizeof(gamestate));    /* Zap the game variables */
  373.     gamestate.weapon = gamestate.pendingweapon = WP_PISTOL;    /* Set the pistol */
  374.     gamestate.health = 100;        /* Reset the health */
  375.     gamestate.ammo = STARTAMMO;    /* Reset the ammo */
  376.     if (!difficulty) {
  377.         gamestate.ammo += STARTAMMO;    /* Double the ammo if easy */
  378.     }        
  379.     gamestate.maxammo = 99;        /* Refill the ammo */
  380.     gamestate.lives = 3;        /* 3 lives */
  381.     gamestate.nextextra = EXTRAPOINTS;    /* Next free life score needed */
  382.     gamestate.godmode = 0;        /* Force god mode off */
  383. }
  384.  
  385. /**********************************
  386.  
  387.     Redraw the main status bar at the bottom
  388.     
  389. **********************************/
  390.  
  391. void RedrawStatusBar(void)
  392. {    
  393.     IO_DrawStatusBar();            /* Draw the status bar */
  394.     IO_DrawFloor(gamestate.mapon);    /* Draw the current floor # */
  395.     IO_DrawScore(gamestate.score);    /* Draw the current score */
  396.     IO_DrawTreasure(gamestate.treasure);    /* Draw the treasure score */
  397.     IO_DrawLives(gamestate.lives);        /* Draw the life count */
  398.     IO_DrawHealth(gamestate.health);    /* Draw the health */
  399.     switch (gamestate.weapon) {            /* Draw the proper ammo */
  400.     case WP_FLAMETHROWER:
  401.         IO_DrawAmmo(gamestate.gas);
  402.         break;
  403.     case WP_MISSILE:
  404.         IO_DrawAmmo(gamestate.missiles);
  405.         break;
  406.     default:
  407.         IO_DrawAmmo(gamestate.ammo);
  408.         break;
  409.     }
  410.     IO_DrawKeys(gamestate.keys);        /* Draw the keys held */
  411.     IO_DrawFace(faceframe);                /* Draw BJ's face */
  412. }
  413.  
  414. /**********************************
  415.  
  416.     Play the game!
  417.     
  418. **********************************/
  419.  
  420. void GameLoop (void)
  421. {
  422.     for(;;) {
  423. skipbrief:        
  424.         ShowGetPsyched();
  425.         PrepPlayLoop();        /* Init internal variables */
  426.         EndGetPsyched();
  427.         PlayLoop();            /* Play the game */
  428.         if (playstate == EX_DIED) {        /* Did you die? */
  429.             --gamestate.lives;            /* Remove a life */
  430.             Died();                        /* Run the death code */
  431.             if (!gamestate.lives) {        /* No more lives? */
  432.                 return;                    /* Exit then */
  433.             }    
  434.             goto skipbrief;                /* Try again */
  435.         }
  436.         
  437.         if (playstate == EX_SECRET) {    /* Going to the secret level? */
  438.             nextmap = MapListPtr->InfoArray[gamestate.mapon].SecretLevel;
  439.         } else if (playstate != EX_WARPED) {
  440.             nextmap = MapListPtr->InfoArray[gamestate.mapon].NextLevel; /* Normal warp? */
  441.         }            /* If warped, then nextmap is preset */
  442.         if (nextmap == 0xffff) {    /* Last level? */
  443.             VictoryScale();                /* You win!! */
  444.             ReleaseMap();        /* Unload the map */
  445.             Intermission();                /* Display the wrapup... */
  446.             ShareWareEnd();            /* End the game for the shareware version */
  447. /*            VictoryIntermission();        /* Wrapup for victory! */
  448.             return;
  449.         }
  450.         ReleaseMap();                /* Unload the game map */
  451.         gamestate.keys = 0;            /* Zap the keys */
  452.         WaitTicks(1);                /* Flush the ticker */
  453.         WaitTicks(30);                /* Wait for the sound to finish */
  454.         if (playstate != EX_WARPED) {    /* No bonus for warping! */
  455.             Intermission();                /* Show the wrap up... */
  456.         }
  457.         gamestate.mapon = nextmap;    /* Next level */
  458.     }
  459. }
  460.